/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
 */

package com.test.cordova;

import android.Manifest;
import android.app.AlertDialog;
import android.app.usage.NetworkStatsManager;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.LifecycleRegistry;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.ViewModel;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.RouteInfo;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.EventLog;
import android.util.Log;
import android.webkit.WebView;
import android.widget.Toast;

import com.github.promeg.pinyinhelper.Pinyin;
import com.github.promeg.tinypinyin.lexicons.android.cncity.CnCityDict;
import com.test.cordova.natives.TestJNI;
import com.test.cordova.observer.NetObserver;
import com.test.cordova.observer.NetStateObservable;
import com.test.cordova.rx.TestRx;
import com.test.cordova.service.DownloadService;
import com.test.cordova.service.InstallApkService;
import com.test.cordova.util.BitmapUtils;
import com.test.cordova.util.CodeUtil;
import com.test.cordova.util.EncodeUtils;
import com.test.cordova.util.Logger;
import com.test.cordova.util.SharedPreferencesUtil;
import com.test.cordova.view.CustomCordovaWebViewImpl;
import com.test.cordova.view.DownloadDialog;
import com.test.cordova.view.LoadingDialog;

import org.apache.cordova.*;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.IllegalFormatCodePointException;
import java.util.List;

public class MainActivity extends CordovaActivity implements CustomCordovaWebViewImpl.OnExitAppListener, NetObserver {


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // enable Cordova apps to be started in the background
        Bundle extras = getIntent().getExtras();
        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
            moveTaskToBack(true);
        }
        startDebugMode();
        startLoad();
        // Set by <content src="index.html" /> in config.xml
        loadUrl(launchUrl);
        //汉子转拼音库
        Pinyin.init(Pinyin.newConfig().with(CnCityDict.getInstance(this)));
        //观察者设计模式
        NetStateObservable.getInstance().registerObserver(MainActivity.this);

        //testScheme();
        //testIp();
        //testIpv6();
        //startDownService();

        //TestJNI jni = new TestJNI();
        //Logger.e("TestJni"," ========    "+jni.handleStr("dnw",3)+"   "+jni.handleStrs("du","ningwei"));

    }

    private void startDownService() {
        Intent it = new Intent(this, DownloadService.class);
        it.putExtra("url", "http://125.88.79.128:29090/wcd_api/file/v1/downloadOpen?fileName=WisdomCampD.apk");
        bindService(it, connection, BIND_AUTO_CREATE);
    }

    private NotifyCallBack notifyCallBack = new NotifyCallBack.Stub() {
        @Override
        public void notifyMainThreadProgress(int progress) throws RemoteException {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (progress == -1) {
                        //下载异常
                        unbindService(connection);
                        dialog.dismiss();
                        return;
                    }
                    if (progress == 100) {
                        //下载完成  关闭弹窗
                        dialog.dismiss();
                    }
                    dialog.setProgressTip(progress);
                    Log.e(TAG, "notifyMainThreadProgress: " + progress + " == " + Thread.currentThread().getName());
                }
            });

        }
    };
    private DownloadAIDL downloadAIDL;
    private DownloadDialog dialog;

    private ServiceConnection connection = new ServiceConnection() {


        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            try {
                if (downloadAIDL == null) {
                    downloadAIDL = DownloadAIDL.Stub.asInterface(service);
                    dialog = new DownloadDialog(MainActivity.this);
                    downloadAIDL.registerProgressCallbck(notifyCallBack);
                }
                if (!dialog.isShowing()) {
                    dialog.show();
                }
                downloadAIDL.startDownload();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            dialog.dismiss();
        }
    };

    private void testIp() {
        try {
            Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();  // 遍历所用的网络接口

            while (en.hasMoreElements()) {
                NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip
                Enumeration<InetAddress> inet = nif.getInetAddresses();                // 遍历每一个接口绑定的所有ip
                Log.e("Test ", "getName : " + nif.getName() + " getDisplayName " + nif.getDisplayName() + " toString " + nif.toString());
                while (inet.hasMoreElements()) {
                    // 在这里如果不加isIPv4Address的判断,直接返回,在4.0上获取到的是类似于fe80::1826:66ff:fe23:48e%p2p0的ipv6的地址
                    InetAddress ip = inet.nextElement();
                    Log.e("Test", "getHostAddress:" + ip.getHostAddress() + " ----- v4  " + (ip instanceof Inet4Address) + "----- v6  " + (ip instanceof Inet6Address));
                    if (!inet.hasMoreElements()) {
                        //没有更多 最后一个 识别ipv6 还是ipv4
                        if (ip instanceof Inet6Address) {
                            if (ip.getHostAddress() != null && !ip.getHostAddress().contains("fe80")) {
                                Log.e("Test", "getHostAddress:" + ip.getHostAddress() + " ----- Inet6Address  ");
                                break;
                            }
                        } else {
                            Log.e("Test", "getHostAddress:" + ip.getHostAddress() + " ----- Inet4Address  ");
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    private void testIpv6() {

        try {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                ConnectivityManager systemService = (ConnectivityManager) getApplication().getSystemService(CONNECTIVITY_SERVICE);
                Network[] activeNetwork = systemService.getAllNetworks();
                Log.e("SDK_INT", "DNS:" + activeNetwork.length);
                if (activeNetwork.length != 0) {

                    LinkProperties linkProperties = systemService.getLinkProperties(activeNetwork[0]);
                    List<InetAddress> dnsServers = linkProperties.getDnsServers();
                    boolean supportIPV6 = false;
                    boolean supportIPV4 = false;
                    for (InetAddress inetAddress : dnsServers) {
                        Log.e("SDK_INT ", "getHostAddress:" + inetAddress.getHostAddress() + " ----- Inet6Address  " + (inetAddress instanceof Inet6Address) + " ----- Inet4Address  " + (inetAddress instanceof Inet4Address));
                        if (inetAddress instanceof Inet4Address) {
                            supportIPV4 = true;
                        } else if (inetAddress instanceof Inet6Address) {
                            if (inetAddress.getHostAddress() != null && !inetAddress.getHostAddress().contains("fe80")) {
                                supportIPV6 = true;
                                break;
                            }
                        }
                    }
                    if (supportIPV6) {
                        Log.e("SDK_INT", "\"[{state:0, error:\\\"\\\"}]\"");
                    } else {
                        if (supportIPV4) {
                            Log.e("SDK_INT", "[{state:-1, error:'不支持ipv6 ,仅支持ipv4'}]");
                        } else {
                            Log.e("SDK_INT", "[{state:-1, error:'不支持ipv6 ,也不支持ipv4'}]");
                        }
                    }

                } else {
                    Log.e("SDK_INT", "wifi 或 数据网没开！");
                }

            } else {
                Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();  // 遍历所用的网络接口
                  /* while (en.hasMoreElements())  {
                       NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip
                       Enumeration<InetAddress> inet = nif.getInetAddresses();                // 遍历每一个接口绑定的所有ip
                       if (nif.getName().equals("wlan0")) {
                           Log.e("Test ","getName : "+ nif.getName() + " getDisplayName " +nif.getDisplayName() +" toString " +nif.toString());
                           while (inet.hasMoreElements()) {
                               InetAddress ip = inet.nextElement();
                               // 在这里如果不加isIPv4Address的判断,直接返回,在4.0上获取到的是类似于fe80::1826:66ff:fe23:48e%p2p0的ipv6的地址
                               Log.e("Test", "getHostAddress:"+ip.getHostAddress() + " ----- v4  " + (ip instanceof Inet4Address) + "----- v6  " + (ip instanceof Inet6Address));
                               if (!ip.isLoopbackAddress() && ip instanceof Inet4Address) {
                                   ipaddress = ip.getHostAddress();
                               }
                           }
                       }
                   }*/
                NetworkInterface wlan0 = NetworkInterface.getByName("wlan0");
                if (wlan0 != null) {
                    Enumeration<InetAddress> inetAddresses = wlan0.getInetAddresses();
                    while (inetAddresses.hasMoreElements()) {
                        InetAddress ip = inetAddresses.nextElement();
                        if (!inetAddresses.hasMoreElements()) {
                            //没有更多 最后一个 识别ipv6 还是ipv4
                            if (ip instanceof Inet6Address) {
                                Log.e("Test", "getHostAddress:" + ip.getHostAddress() + " ----- Inet6Address  ");
                            } else {
                                Log.e("Test", "getHostAddress:" + ip.getHostAddress() + " ----- Inet4Address  ");
                            }
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }

    }

    private void testScheme() {
        //scheme   启动方式1
        //wisdomcampd://?from=whereParm&username=userParm&passWord=pswParm&ts=timeParm
        String[] allEncode = EncodeUtils.allEncode("cj_zhoujj", "123456!Ab");
        StringBuilder sb = new StringBuilder("wisdomcampd://?");
        sb.append("from=").append("yiqiwei")
                .append("&username=").append(allEncode[0])
                .append("&passWord=").append(allEncode[1])
                .append("&ts=").append(System.currentTimeMillis());
        Uri uri = Uri.parse(sb.toString());
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        startActivity(intent);
        //scheme   启动方式 2   <a href="wisdomcampd://?from=whereParm&username=userParm&passWord=pswParm&ts=timeParm">打开app</a><br/>
    }

    public String getLocalMacAddress() {
        WifiManager wifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        WifiInfo info = wifi.getConnectionInfo();
        Log.e("WifiInfo:", "" + info.toString());
        return info.getMacAddress();
    }


    private void testRequestPermission() {

        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.READ_CONTACTS, Manifest.permission.MODIFY_PHONE_STATE}, 23);
        int state = ContextCompat.checkSelfPermission(this, Manifest.permission.MODIFY_PHONE_STATE);
        if (state == PackageManager.PERMISSION_DENIED) {
            Log.e(TAG, "未授权");
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.MODIFY_PHONE_STATE}, 23);
            // requestPermissions(new String[]{ Manifest.permission.MODIFY_PHONE_STATE},23);
        } else if (state == PackageManager.PERMISSION_GRANTED) {
            Log.e(TAG, "授权");
        }

        //尝试捆绑app 后台安装
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            startInstanllApk();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }
    }

    /**
     * 测试绑定安装
     */
    private void startApkService() {
        Boolean isTip = false;
        if (SharedPreferencesUtil.contains(this, "isTip")) {
            isTip = SharedPreferencesUtil.getBoolean(this, "isTip", false);
        }
        if (!isTip) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                startInstanllApk();
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            }
        }
    }

    private void startInstanllApk() {
        Intent it = new Intent(this, InstallApkService.class);
        startService(it);
    }

    private void startDebugMode() {
        final String packageName = getPackageName();
        final PackageManager pm = getPackageManager();

        try {
            ApplicationInfo appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
            if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
                WebView.setWebContentsDebuggingEnabled(true);
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected CordovaWebView makeWebView() {
        CustomCordovaWebViewImpl cordovaWebView = new CustomCordovaWebViewImpl(makeWebViewEngine());
        cordovaWebView.setOnExitAppListener(this);

        return cordovaWebView;
    }

    /**
     * 显示进度界面
     */
    private void startLoad() {
        LoadingDialog.show(this);
    }

    /**
     * 关闭进度界面
     */
    private void endLoad() {
        LoadingDialog.dismiss();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

        if (requestCode == 23) {
            int length = grantResults.length;
            for (int i = 0; i < length; i++) {
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {//权限被打开
                    Log.e(TAG, "获取" + permissions[i] + "的权限打开了");
                } else {
                    Log.e(TAG, "获取" + permissions[i] + "的权限被拒了");
                }
            }
        }
        if (requestCode == 1) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {//权限被打开
                startInstanllApk();
                Log.e(TAG, "获取" + permissions[0] + "的权限打开了");
            } else {
                Log.e(TAG, "获取" + permissions[0] + "的权限被拒了");
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        try {
            if (downloadAIDL != null) {
                downloadAIDL.unRegisterProgressCallbck(notifyCallBack);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        NetStateObservable.getInstance().unRegisterAllObserver();
    }

    @Override
    public Object onMessage(String id, Object data) {
        Log.e(TAG, "onMessage: " + id);
        switch (id) {
            case "onPageStarted":
                //加载页面开始
                break;

            case "onPageFinished":
                //加载页面完成
                Log.e(TAG, " onPageFinished " + data.toString());
                endLoad();
                break;
            case "onReceivedError":
                //加载页面完成
                Log.e(TAG, data.toString());
                endLoad();
                String failingUrl = "";
                String errorUrl = preferences.getString("errorUrl", null);
                try {
                    JSONObject root = new JSONObject(data.toString());
                    failingUrl = root.getString("url");
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                if ((errorUrl != null) && (!failingUrl.equals(errorUrl)) && (appView != null)) {
                    // Load URL on UI thread
                    runOnUiThread(new Runnable() {
                        public void run() {
                            appView.showWebPage(errorUrl, false, true, null);
                        }
                    });
                } else {
                    AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setTitle("加载失败");
                    builder.setMessage("加载失败，请刷新重试")
                            .setPositiveButton("重试", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    startLoad();
                                    loadUrl(launchUrl);
                                }
                            })
                            .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    finish();
                                }
                            });

                    AlertDialog dialog = builder.create();
                    dialog.setCancelable(false);
                    dialog.show();
                }

                break;
        }
        return null;
    }

    private long firstTime;

    @Override
    public void onExitApp() {
        if (System.currentTimeMillis() - firstTime > 2000) {
            Toast.makeText(this, "再按一次退出应用", Toast.LENGTH_SHORT).show();
            firstTime = System.currentTimeMillis();
        } else {
            Intent it = new Intent();
            it.putExtra("sss", "main_exit");
            setResult(RESULT_OK, it);
            finish();
        }
    }

    @Override
    public void netStateChange(Object... objects) {
        for (Object o : objects) {
            Log.e("netStateChange:", "" + o.toString());
        }
    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }

}
